#ifndef _EVENT_H_
#define _EVENT_H_

#include <string>
#include <memory>

namespace Engine2D
{


    enum EventType
    {
        T_CommonEvent,                    /**< Common event data */
        T_DisplayEvent,                   /**< Display event data */
        T_WindowEvent,                    /**< Window event data */
        T_KeyboardEvent,                  /**< Keyboard event data */
        T_TextEditingEvent,               /**< Text editing event data */
        T_TextInputEvent,                 /**< Text input event data */
        T_MouseMotionEvent,               /**< Mouse motion event data */
        T_MouseButtonEvent,               /**< Mouse button event data */
        T_MouseWheelEvent,                /**< Mouse wheel event data */
        T_JoyAxisEvent,                   /**< Joystick axis event data */
        T_JoyBallEvent,                   /**< Joystick ball event data */
        T_JoyHatEvent,                    /**< Joystick hat event data */
        T_JoyButtonEvent,                 /**< Joystick button event data */
        T_JoyDeviceEvent,                 /**< Joystick device change event data */
        T_ControllerAxisEvent,            /**< Game Controller axis event data */
        T_ControllerButtonEvent,          /**< Game Controller button event data */
        T_ControllerDeviceEvent,          /**< Game Controller device event data */
        T_ControllerTouchpadEvent,        /**< Game Controller touchpad event data */
        T_ControllerSensorEvent,          /**< Game Controller sensor event data */
        T_AudioDeviceEvent,               /**< Audio device event data */
        T_SensorEvent,                    /**< Sensor event data */
        T_QuitEvent,                      /**< Quit request event data */
        T_UserEvent,                      /**< Custom event data */
        T_SysWMEvent,                     /**< System dependent window event data */
        T_TouchFingerEvent,               /**< Touch finger event data */
        T_MultiGestureEvent,              /**< Gesture event data */
        T_DollarGestureEvent,             /**< Gesture event data */
        T_DropEvent                       /**< Drag and drop event data */
    };

    class Event
    {
    public:
        Event(EventType type = T_CommonEvent, const std::string name = "CommonEvent") : m_type(type), m_name(name) {}
        virtual ~Event() = default;
        EventType Type() { return m_type; } 
        std::string Name() { return m_name; }
    protected: 
        EventType m_type;
        std::string m_name;
    };
    using EventPtr = std::shared_ptr<Event>;

    class EventDispatcher
    {
    public:
        EventDispatcher(EventPtr & event) : m_event(event) {}
        virtual ~EventDispatcher() = default;
        template<typename E, typename F>
        void Dispatcher(F && fn)
        {
            if (m_event->Type() == E::GetType()) {
                fn(m_event);
            }
        }
    private:
        EventPtr m_event;
    };

    #define REGISTER_EVENT(type)                \
    public:                                     \
        static EventType GetType() {            \
            return EventType::type;             \
        }                       

} // namespace Engine2D


#endif